import java.util.*;
import java.io.*;


class Util {
	static void indent(PrintStream ps, int indentLevel) {
		for (int n = 0; n < indentLevel; n++) {
			ps.print("\t");
		}
	}	
}

// 语法树节点
class SyntaxTreeNode implements Serializable {
	
}

class Type extends SyntaxTreeNode {
	
}

class PrimitiveType extends Type {
	
}

class IntType extends PrimitiveType {
	static IntType the = new IntType();
	public String toString() {
		return "int";
	}
}

class DoubleType extends PrimitiveType {
	static DoubleType the = new DoubleType();
	public String toString() {
		return "double";
	}
}

class VoidType extends PrimitiveType {
	static VoidType the = new VoidType();
	public String toString() {
		return "void";
	}
	
}

class UserDefinedType extends Type {
	String mName;
	Type mBaseType;
	ArrayList<VariableDeclaration> mFields;	
}

class VariableDeclaration extends SyntaxTreeNode {
	Type mType;
	String mName;
	public void saveAsReadable(PrintStream ps, int indentLevel) {
		Util.indent(ps, indentLevel);
		ps.print(mType);
		ps.print(" ");
		ps.print(mName);
		ps.println(";");
	}
}



abstract class Statement extends SyntaxTreeNode {
	public abstract void saveAsReadable(PrintStream ps, int indentLevel);
}

class IfStatement extends Statement {
	Expression mCondition;
	Statement mTrueBranch;
	Statement mFalseBranch;
	public void saveAsReadable(PrintStream ps, int indentLevel) {
		Util.indent(ps, indentLevel);
		ps.println("if () {");
		ps.println("}");
	}
	
}

class AssignmentStatement extends Statement {
	Variable mVariable;
	Expression mValueExpression;
	public void saveAsReadable(PrintStream ps, int indentLevel) {
		Util.indent(ps, indentLevel);
		ps.print(mVariable);
		ps.print(" = ");
		ps.print(mValueExpression);
		ps.println(";");
	}
}

class Expression extends SyntaxTreeNode {
}

class BinaryExpression extends Expression {
//	Operator mOperator;
} 


class UnaryExpression extends Expression {
//	Operator mOperator;
} 

class Variable extends Expression {
	String mName;
	public String toString() {
		return mName;
	}
	
}

class IntConstant extends Expression {
	int mValue;
	public String toString() {
		return Integer.toString(mValue);
	}
}

class DoubleConstant extends Expression {
	double mValue;
	public String toString() {
		return Double.toString(mValue);
	}
}

class Function extends SyntaxTreeNode {
	Type mReturnType;
	String mName;
	ArrayList<VariableDeclaration> mParameters = new ArrayList<VariableDeclaration>();
	ArrayList<VariableDeclaration> mLocalVariables = new ArrayList<VariableDeclaration>();
	ArrayList<Statement> mStatements = new ArrayList<Statement>();
	public void saveAsReadable(PrintStream ps, int indentLevel) {
		// 打印函数原型
		Util.indent(ps, indentLevel);
		ps.print(mReturnType);
		ps.print(" ");
		ps.print(mName);
		ps.print("(");
		ps.println(")");

		// 打印函数体
		Util.indent(ps, indentLevel);
		ps.println("{");

		for (VariableDeclaration d : mLocalVariables) {
			d.saveAsReadable(ps, indentLevel + 1);
		}

		for (Statement s : mStatements) {
			s.saveAsReadable(ps, indentLevel + 1);
		}
		
		Util.indent(ps, indentLevel);
		ps.println("}");
	}	
}

class Program extends SyntaxTreeNode {
	String mName;
	ArrayList<Function> mFunctions = new ArrayList<Function>();
	public void saveAsReadable(PrintStream ps, int indentLevel) {
		ps.print("program ");
		ps.println(mName);

		for (Function f : mFunctions) {
			f.saveAsReadable(ps, indentLevel + 1);	
		}
		
		ps.println("end");
	}
}

public class Main {
	public static void main(String[] args) throws Exception {

		// 函数foo
		Function funcFoo = new Function();
		funcFoo.mName = "foo";
		funcFoo.mReturnType = IntType.the;
		

		// 主函数
		Function funcMain = new Function();
		funcMain.mName = "main";
		funcMain.mReturnType = VoidType.the;

		// 声明一个变量：int x;
		VariableDeclaration d = new VariableDeclaration();
		d.mType = IntType.the;
		d.mName = "x";
		funcMain.mLocalVariables.add(d);

		// 一条赋值语句：x = 2；
		AssignmentStatement s1 = new AssignmentStatement();
		s1.mVariable = new Variable();
		s1.mVariable.mName = "x";
		IntConstant intconst1 = new IntConstant();
		intconst1.mValue = 2;
		s1.mValueExpression = intconst1;
		funcMain.mStatements.add(s1);

		// 程序		
		Program program = new Program();
		program.mName = "helloworld";
		program.mFunctions.add(funcFoo);
		program.mFunctions.add(funcMain);


		// 用序列化的能力将内存中的语法树保存至文件
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("helloworld.unreadable.nc"));
		out.writeObject(program);

		//ObjectInputStream in = new ObjectInputStream(new FileInputStream("helloworld.nc"));
		//Program anotherProgram = (Program)in.readObject();

		// 用人类可读的形式将语法树保存至文件
		//PrintStream ps = System.out;
		File sourceFile = new File("helloworld.nc");
		PrintStream ps = new PrintStream(sourceFile);

		program.saveAsReadable(ps, 0);
	}
}
